using System.Diagnostics;

namespace _ReplaceString_.UI;

public class UIBase : UIElement
{
	public event Func<UIBase, bool>? OnRecalculate;

	private List<UIStyle> _styles = new();

	private Dictionary<Type, UIStyle> _uniqueStyles = new();

	protected IEnumerable<UIStyle> Styles => Parent is not UIBase ui ? _styles :
		ui.Styles.Where(t => t.Inherit)
		   .Where(t => !t.Unique || _styles.Where(s => s.Unique).All(s => s.GetType().BaseType != t.GetType().BaseType)).Concat(_styles);

	public void AddStyle(UIStyle style)
	{
		if (style.Unique)
		{
			var baseType = style.GetType().BaseType;
			Debug.Assert(baseType != null, "不可能是object");
			if (_uniqueStyles.TryGetValue(baseType, out var exist))
			{
				_styles.Remove(exist);
			}
			_uniqueStyles[baseType] = style;
		}
		_styles.Add(style);

		style.Apply(this);
	}

	public void AddStyle(params UIStyle[] styles)
	{
		foreach (var style in styles)
		{
			AddStyle(style);
		}
	}

	public override void Update(GameTime gameTime)
	{
		foreach (var style in Styles)
		{
			style.Update(this);
		}
		base.Update(gameTime);
	}

	public override void DrawSelf(SpriteBatch spriteBatch)
	{
		foreach (var style in Styles)
		{
			style.Draw(this);
		}
	}

	public override void Recalculate()
	{
		base.Recalculate();
		if (OnRecalculate != null)
		{
			if (OnRecalculate.Invoke(this))
			{
				base.Recalculate();
			}
		}
	}

	public Color ForegroundColor { get; set; } = Color.White;

	public Color BackgroundColor { get; set; } = Color.Transparent;

	public Color ExtraColor { get; set; } = Color.White;

	public UITag Tag { get; set; }

	public void Move(Vector2 offset)
	{
		Left.Pixels += offset.X;
		Top.Pixels += offset.Y;
	}

	public void MoveTo(Vector2 position)
	{
		Left.Set(position.X, 0);
		Top.Set(position.Y, 0);
	}

	public void NextTo(UIElement ui, Direction direction)
	{
		switch (direction)
		{
			case Direction.Left:
				(Left, Top) = (ui.Left, ui.Top);
				Left.Pixels -= Width.Pixels;
				break;

			case Direction.Right:
				(Left, Top) = (ui.Left, ui.Top);
				Left.Pixels += ui.GetOuterDimensions().Width;
				break;

			case Direction.Up:
				(Left, Top) = (ui.Left, ui.Top);
				Top.Pixels -= Height.Pixels;
				break;

			case Direction.Down:
				(Left, Top) = (ui.Left, ui.Top);
				Top.Pixels += ui.GetOuterDimensions().Height;
				break;

			case Direction.Zero:
				(Left, Top) = (ui.Left, ui.Top);
				break;

			default:
				throw new NotImplementedException("摸了");
		}
	}

	public Vector2 Position => new Vector2(_dimensions.X, _dimensions.Y);

	public Vector2 Size => new Vector2(_dimensions.Width, _dimensions.Height);

	public Rectangle OuterBox => new Rectangle((int)_outerDimensions.X, (int)_outerDimensions.Y, (int)_outerDimensions.Width, (int)_outerDimensions.Height);

	public Rectangle Box => new Rectangle((int)_dimensions.X, (int)_dimensions.Y, (int)_dimensions.Width, (int)_dimensions.Height);

	public Rectangle InnerBox => new Rectangle((int)_innerDimensions.X, (int)_innerDimensions.Y, (int)_innerDimensions.Width, (int)_innerDimensions.Height);
}